package sjc;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.apache.zookeeper.data.Stat;

import java.util.Collections;

public class CrudTest {
    public static void main(String[] args) throws Exception {
        String zkIpPort = "192.168.72.133:2181";
        ExponentialBackoffRetry retryPolicy = new ExponentialBackoffRetry(1000, 3, Integer.MAX_VALUE);
        CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient(zkIpPort, retryPolicy);
        curatorFramework.start();

        // ===========创建节点
        curatorFramework.create()
                .creatingParentsIfNeeded()  // 递归创建,自动创建父节点
                .withMode(CreateMode.PERSISTENT)    // 持久节点
//                .withMode(CreateMode.CONTAINER)         // 容器节点， 当最后一个子节点删除，服务器会在未来某段时间内删除该节点
                .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE) // 设置ACL
                .forPath("/node10/child_01", "123456".getBytes());


        curatorFramework.create()
                .withTtl(3000)  // 设置临时节点的有效期，毫秒
                .creatingParentsIfNeeded()
                .withMode(CreateMode.PERSISTENT_SEQUENTIAL_WITH_TTL) // 定时节点，在一定的时间内，没有操作该节点，且该节点没有子节点，服务器自动删除该节点
                .withACL(Collections.singletonList(new ACL(ZooDefs.Perms.ALL, new Id("digest", "wangsaichao:G2RdrM8e0u0f1vNCj/TI99ebRMw="))))
                .forPath("/node12", "123".getBytes());

        // ============获取节点
        Stat node10Stat = new Stat();
        byte[] node10 = curatorFramework.getData().storingStatIn(node10Stat).forPath("/node10/child_01");
        System.out.println("该节点信息 ==> "+ new String(node10));
        System.out.println("该节点的数据版本号 ===> " + node10Stat.getVersion());

        // 获取节点信息，并加 watcher事件，watcher只能触发一次
        byte[] bytes = curatorFramework.getData().usingWatcher(new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                System.out.println("----> watcher触发了。。。。");
                System.out.println(watchedEvent);
            }
        }).forPath("/node10/child_01");
        System.out.println("获取到的节点数据 === > " + new String(bytes));
        Thread.sleep(10000);

        // =============修改节点
        Stat stat = curatorFramework.setData()
                                .withVersion(-1)
                                .forPath("/node10/child_01", "I love you".getBytes());
        System.out.println("修改之后的版本 === > "+ stat.getVersion());

        // ==============删除节点
        // 删除节点，不递归
        Void aVoid = curatorFramework.delete().forPath("/node10");
        System.out.println("=====> " + aVoid);

        // 删除节点，递归
        curatorFramework.delete()
                        .deletingChildrenIfNeeded()
                        .forPath("/node10");

        curatorFramework.delete().guaranteed().forPath("/node11");

        // =========判断节点是否存在
        Stat existsNodeStat = curatorFramework.checkExists().forPath("/node10");
        if(existsNodeStat == null){
            System.out.println("====> 节点不存在");
        }
        if(existsNodeStat.getEphemeralOwner() > 0){
            System.out.println("====> 临时节点");
        }else{
            System.out.println("====> 持久节点");
        }

        curatorFramework.close();
    }
}
